#pragma once

#include "type_traits.hpp"

namespace zuck
{
	namespace __detail
	{
		class _ConstructFunctor {
		public:
			template<typename T, typename ...Args>
			inline void operator()(T* const ptr, Args&&... args) const
			{
				::new (static_cast<void*>(ptr)) T(::zuck::forward<Args>(args)...);
			}

			template<typename T, typename ...Args>
			inline void operator()(T& obj, Args&&... args) const
			{
				::new (static_cast<void*>(&obj)) T(::zuck::forward<Args>(args)...);
			}

			template<typename T>
			inline void operator()(T& obj) const
			{
				obj.~T();
			}
		};
	}
	constexpr __detail::_ConstructFunctor cconstruct = {};
	
	template<typename T, typename ...Args>
	void construct(T* const ptr, Args&&... args)
	{
		::new (void* (ptr)) T(zuck::forward<Args>(args)...);
	}

	template<typename T, typename ...Args>
	void construct(T& obj, Args&&... args)
	{
		::new ((void*) &obj) T(zuck::forward<Args>(args)...);
	}

	template<typename T>
	void destruct(T& obj)
	{
		obj.~T();
	}
}

